package com.yb.livewykt.ui.model

import android.content.Intent
import android.os.Environment
import android.os.Handler
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.MutableLiveData
import com.netease.LSMediaCapture.lsLogUtil
import com.netease.LSMediaCapture.lsMediaCapture
import com.netease.LSMediaCapture.lsMessageHandler
import com.netease.LSMediaCapture.lsMessageHandler.*
import com.netease.vcloud.video.effect.VideoEffect
import com.yb.livewykt.R
import com.yb.livewykt.bean.*
import com.yb.livewykt.databinding.ActivityLiveStreamingLayoutBinding
import com.yb.livewykt.ui.inter.OnFUControlListener
import com.yb.livewykt.ui.model.FURendererKt.Companion.EXTERNAL_INPUT_TYPE_VIDEO
import com.yb.livewykt.util.CameraUtils
import com.yb.livewykt.util.showToast
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class LiveStreamPanel(
    val activity: AppCompatActivity,
    private val binding: ActivityLiveStreamingLayoutBinding
) :
    lsMessageHandler {

    private val TAG = javaClass.simpleName

    private var publishParam:PublishParam = PublishParam(
        "",
        lsMediaCapture.StreamType.AV,
        lsMediaCapture.FormatType.RTMP,
        Environment.getDataDirectory().path,
        lsMediaCapture.VideoQuality.HD1080P,
        isScale_16x9 = false,
        useFilter = false,
        filterType = VideoEffect.FilterType.none,
        frontCamera = false,
        waterMask = false,
        qosEnable = true,
        graffitiOn = false,
        isUploadLog = true
    )

    private var fuRendererKt:FURendererKt = initRuRendererKt()
    private val onFuControl:OnFUControlListener = fuRendererKt

    val networkDisconnect = MutableLiveData<Boolean>()

    private var capture: lsMediaCapture? = null
    private var para:lsMediaCapture.LiveStreamingPara? = null
    private var isLiving:Boolean = false
    private var liveStreamingInit:Boolean = false
    private var startCameraVideo:Boolean = false
    private var intent = Intent("LiveStreamingStopFinished")

    private var clickTime:Long = 0L

    private var liveThread:Thread? = null
    private var handle:Handler = Handler()

    init {
        FURendererKt.initFURenderer(activity)
        fuRendererKt.onSurfaceCreated()
        fuRendererKt.cameraChanged()
        onFuControl.onBlurTypeSelected(2f)
    }

    private fun readyPreview(){
        val lsPara = lsMediaCapture.LsMediaCapturePara()
        lsPara.Context = activity
        lsPara.setMessageHandler(this)
        lsPara.setLogLevel(lsLogUtil.LogLevel.INFO)
        lsPara.uploadLog = true
        capture = lsMediaCapture(lsPara)
    }

    fun startPreview(){
        readyPreview()
        try {
            readyLive()
            capture?.startVideoPreview(
                binding.neteaseView,
                true,
                publishParam.useFilter,
                publishParam.videoQuality,
                publishParam.isScale_16x9
            )
            capture?.setCaptureRawDataCB { p0, p1, p2, p3, _->fuRendererKt.onDrawFrame(p0, p1, p2, p3) };
            startCameraVideo = true
        }catch (e: Exception){
            e.printStackTrace()
        }
    }

    fun setPushUrl(url: String){
        publishParam.pushUrl = url
        para = lsMediaCapture.LiveStreamingPara()
        para?.streamType = publishParam.streamType
        para?.formatType = publishParam.formatType
        para?.recordPath = publishParam.recordPath
        para?.qosOn = publishParam.qosEnable
    }

    fun startLive(){

        readyLive()

        var time = System.currentTimeMillis()
        if (time - clickTime < 1000){
            return
        }
        clickTime = time
        if (!isLiving){
            activity.resources.getString(R.string.start_live).showToast()
            liveThread = object : Thread() {
                override fun run() {
                    if (!readyLive()){
                        handle.sendEmptyMessage(50)
                    }
                }
            }
            liveThread?.start()
        }
    }

    private fun readyLive() : Boolean{
        liveStreamingInit = capture?.initLiveStream(para, publishParam.pushUrl)!!
        if (liveStreamingInit){
            capture?.startLiveStreaming()
            isLiving = true
            return true
        }
        return liveStreamingInit
    }
    fun stopLive(){
        activity.resources.getString(R.string.stop_live).showToast()
        capture?.stopLiveStreaming()

        capture?.releaseMessageHandler()
        activity.resources.getString(R.string.stop_live_success).showToast()

    }

    fun onConfigurationChanged() {
        capture?.onConfigurationChanged()

    }

    fun setFilterName(filter: Filter){
        Log.d(TAG, "setFilterName: $filter")
        onFuControl.onFilterNameSelected(filter.name)
    }
    fun setFilterLevel(level:Float){
        onFuControl.onFilterLevelSelected(level)
    }

    fun setBeautyLevel(beauty: Beauty?,level: Float){
        Log.d(TAG, "setBeautyLevel: ${beauty?.key} \t $level")
        if (beauty == null) return
        when(beauty.key){
            FuBeautyEnum.RESET.key ->{
                onFuControl.onBlurLevelSelected(0f)
                onFuControl.onColorLevelSelected(0f)
                onFuControl.onCheekThinningSelected(0f)
                onFuControl.onIntensityNoseSelected(0f)
                onFuControl.onEyeEnlargeSelected(0f)
            }
            FuBeautyEnum.BLURWHIT.key ->{
                onFuControl.onBlurLevelSelected(level)
            }
            FuBeautyEnum.BEAUTYWHITE.key ->{
                onFuControl.onColorLevelSelected(level)
            }
            FuBeautyEnum.THINFACE.key ->{
                onFuControl.onCheekThinningSelected(level)
            }
            FuBeautyEnum.THINNOSE.key ->{
                onFuControl.onIntensityNoseSelected(level)
            }
            FuBeautyEnum.BIGEYES.key ->{
                onFuControl.onEyeEnlargeSelected(level)
            }
        }
    }

    fun switchCamera(){
        capture?.switchCamera()
    }



    override fun handleMessage(i0: Int, i1: Any?) {
        Log.d(TAG, "handleMessage: $i0 \t $i1")
        when(i0){
            MSG_INIT_LIVESTREAMING_OUTFILE_ERROR -> {
                Log.d(TAG, "handleMessage: 1")
                activity.resources.getString(R.string.init_live_error).showToast()
            }
            MSG_INIT_LIVESTREAMING_VIDEO_ERROR -> {
                Log.d(TAG, "handleMessage: 2")
                activity.resources.getString(R.string.init_live_error).showToast()
            }
            MSG_INIT_LIVESTREAMING_AUDIO_ERROR -> {
                Log.d(TAG, "handleMessage: 3")
                activity.resources.getString(R.string.init_live_error).showToast()
            }
            MSG_START_LIVESTREAMING_ERROR -> {
                Log.d(TAG, "handleMessage: 4")
                activity.resources.getString(R.string.init_live_error).showToast()
            }
            MSG_START_PREVIEW_ERROR -> {
                activity.resources.getString(R.string.can_not_preview).showToast()
            }
            MSG_AUDIO_RECORD_ERROR -> {
                activity.resources.getString(R.string.can_not_record).showToast()
            }
            MSG_RTMP_URL_ERROR -> {
                activity.resources.getString(R.string.net_work_disconnect).showToast()
                networkDisconnect.value = true
            }
            MSG_START_LIVESTREAMING_FINISHED -> {
                activity.resources.getString(R.string.start_living).showToast()
            }
            50 ->{
                Log.d(TAG, "handleMessage: 50")
                activity.resources.getString(R.string.init_live_error).showToast()
            }
        }
    }

    private fun initRuRendererKt() : FURendererKt{
        return FURendererKt.Builder(activity)
            .setMaxFaces(2)
            .setNeedFaceBeauty(true)
            .setExternalInputType(EXTERNAL_INPUT_TYPE_VIDEO)
            .inputImageOrientation(CameraUtils.getFrontCameraOrientation())
            .inputTextureType(FURendererKt.FU_ADM_FLAG_EXTERNAL_OES_TEXTURE)
            .setOnSystemErrorListener(object : FURendererKt.OnSystemErrorListener {
                override fun onSystemError(error: String?) {
                    Log.d(TAG, "onSystemError: $error")
                }
            })
            .build()
    }

}